import os
import subprocess
from spk.core.workspace import *
from spk.template.debian import *


class StepDebianWithBinary(SpkWorker):
    '''基于 二进制文件 构建 debian 包
    
    这是一个简单的工作流
    1. 此工作需要您提供基础包信息
    2. 上传您的可执行文件用于构建
    3. 构建您的软件包并查看构建结果
    4. 下载您构建的软件包
    '''

    First  = "第一步: 构建 Debian 信息"
    Second = "第二步: 上传可执行文件"
    Third  = "第三步: 构建 deb 包"
    Fourth = "第四步: 构建结果"
    Five   = "第五步: 下载 deb 包"

    def __init__(self):
        print('__init__')
        for k, v in class_keys(DebFields).items():
            set(k, "")

    def __del__(self):
        print('__del__')
        for k, v in class_keys(DebFields).items():
            unset(k)

    __steps__ = [
        First, Second, Third, Fourth, Five
    ]

    def __at__(self, i):
        return self.__steps__[i]

    __keywords__ = [
            'upload-filepath',
            'debian-code',
            'debian-code',
            'debian-result',
            'debian-deb',
        ]

    def __do_clean__(self):
        print('__do_clean__')
        for k in self.__keywords__:
            unset(k)
    
    def __do_work__(self):
        print('__do_work__')
        # 第一步: 构建 Debian 信息
        if current() == self.First:
            for k,tuple_v in class_keys(DebFields).items():
                v = tuple_v[0]
                dv = tuple_v[1]
                if isinstance(dv, list):
                    if get(k) == '':
                        set(k, dv[0])
                    set(k,st.sidebar.selectbox(f'{v}({k})', dv, index=dv.index(get(k))))
                else:
                    if get(k) == '':
                        set(k, dv)
                    set(k,st.sidebar.text_input(f'{v}({k})', get(k), placeholder=dv))
            
            
            st.table([v for v in st.session_state.items() if v[0] in class_keys(DebFields).keys()])
            
            # 检查是否有未填写的字段
            intercept = False
            for k, v in class_keys(DebFields).items():
                if get(k) == '':
                    intercept = True
                    break

            if intercept:
                st.button(f'请填写 {v[0]}({k})', disabled=intercept)
            else:
                next_step(False)

        # 第二步: 上传可执行文件
        if current() == self.Second:
            prev_step(False)

            debian_modes = ['为可执行文件构建软件包']
            st.selectbox('构建模式', debian_modes)

            if get('upload-filepath') is None:
                save_paths = [
                    '/usr/bin',
                ]
                save = st.selectbox('保存路径', save_paths)
                if upload_file := st.file_uploader('选择可执行文件', accept_multiple_files=False):
                    st.write(f'准备上传文件: {upload_file.name}')
                    
                    set('upload-filepath', get('workdir') + '/' + upload_file.name)

                    with st.spinner('正在保存文件...'):
                        with open(get('upload-filepath'), 'wb') as file:
                            file.write(upload_file.getvalue())

                            st.rerun()
                
            else:
                st.write(f'文件路径: {get("upload-filepath")}')

                next_step(False)

        # 第三步: 构建 deb 包
        if current() == self.Third:
            prev_step(False)

            st.code(control(), language='ini')

            if st.button('已确认以上信息，开始构建'):
                
                with st.spinner('正在构建 deb 包...'):

                    os.system(f'chmod +x {get("upload-filepath")}')

                    prefix = os.path.join(get('workdir'), "DEBIAN")
                    if not os.path.exists(prefix):
                        os.makedirs(prefix, mode=0o755)

                    with open(os.path.join(prefix, "control"), 'w') as file:
                        file.write(control())

                    prefix = os.path.join(get('workdir'), 'usr', 'bin')
                    if not os.path.exists(prefix):
                        os.makedirs(prefix, mode=0o755)

                    os.system(f'mv {get("upload-filepath")} {prefix}')

                    command = [
                        "dpkg-deb",
                        "--build",
                        get('workdir'),

                    ]
                    p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                    stdout, stderr = p.communicate()

                    set('debian-code', p.returncode)
                    if p.returncode != 0:
                        set('debian-result', stderr.decode())
                    else:
                        set('debian-result', stdout.decode())

                    next_step()

        # 第四步: 构建结果
        if current() == self.Fourth:
            prev_step(False)

            st.write('构建结果:')
            if get('debian-code') == 0:
                st.success('构建成功')
                set('debian-deb', f'{get("workdir")}.deb')
            else:
                st.error('构建失败')

            st.write('构建日志:')
            st.code(get('debian-result'), wrap_lines=True)

            if get('debian-code') == 0:
                next_step(False)
        
        # 第五步: 下载 deb 包
        if current() == self.Five:
            prev_step(False)

            filename = f'{get("Package")}_{get("Version")}_{get("Architecture")}.deb'
            st.code(f'下载: {filename}')
            st.download_button(f'下载: {filename}', 
                        data=open(get('debian-deb'), 'rb').read(), 
                        file_name=filename)